package com.zxq.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sun.jmx.snmp.tasks.Task;
import com.zxq.exchange.enums.EProtocol;
import com.zxq.exchange.enums.EFrame;
import com.zxq.tcp.TcpNetty;
import com.zxq.web.dto.PlatformProjectDTO;
import com.zxq.web.enums.ECodeEnum;
import com.zxq.web.enums.EProductState;
import com.zxq.web.factory.TCPDispatchHandlerFactory;
import com.zxq.web.iot.domain.IotProject;
import com.zxq.web.iot.domain.IotProjectFrame;
import com.zxq.web.iot.service.impl.IotDeviceServiceImpl;
import com.zxq.web.iot.service.impl.IotProjectFrameServiceImpl;
import com.zxq.web.iot.service.impl.IotProjectServiceImpl;
import com.zxq.web.vo.ResultVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

/**
 * 启动产品服务
 */
@RestController("product")
@Slf4j
public class IOTProductController {




    /**
     * 产品服务
     */
    @Autowired
    IotProjectServiceImpl iotProductDoService;


    /**
     * 产品对应的帧格式服务
     */
    @Autowired
    IotProjectFrameServiceImpl iotProjectFrameDoService;

    /**
     * 设备服务
     */
    @Autowired
    IotDeviceServiceImpl iotDeviceService;





    /**
     * netty保存产品id，和task任务的接口
     */
    ConcurrentHashMap<Long, Task> nettyTask = new ConcurrentHashMap<>();
    ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(2);

    @PostMapping("startOver")
    public ResultVO<String> startProductServer(PlatformProjectDTO platformProjectDTO) {

        Long productId  = platformProjectDTO.getProjectId();
        ResultVO<String> resultVO = new ResultVO<>();
        IotProject iotProjectDo = iotProductDoService.selectIotProjectById(platformProjectDTO.getProjectId());

        IotProject queryCondition = new IotProject();
        queryCondition.setTransferPort(iotProjectDo.getTransferPort());

        Boolean existTcpServer = iotProductDoService.selectIotProjectList(queryCondition).size() > 0;
        if(existTcpServer) {
            resultVO.setSuccess(false);
            resultVO.setCode(ECodeEnum.ProductPortAlreadyUse.getCode());
            resultVO.setMessage(ECodeEnum.ProductPortAlreadyUse.getMsg());
            resultVO.setData(iotProjectDo.getName());
            return resultVO;
        }

        Long operatorId  = platformProjectDTO.getOperatorId();
        if(iotProjectDo.getCreator() != operatorId) {
            resultVO.setSuccess(false);
            resultVO.setCode(ECodeEnum.UserNoPermission.getCode());
            resultVO.setMessage(ECodeEnum.UserNoPermission.getMsg());
            resultVO.setData(iotProjectDo.getName());
            return resultVO;
        }

        switch (EProductState.getType(iotProjectDo.getState().intValue())) {
            case alreadyPay:
            case stop:
                {
                Integer port = iotProjectDo.getTransferPort().intValue();
                Integer protocol = iotProjectDo.getProtocolType().intValue();
                EProtocol eProtocol = EProtocol.getType(protocol);
                switch (eProtocol) {
                    case TCP:{
                        TcpNetty tcpNetty = new TcpNetty(port);
                        //需要添加分发逻辑
                        IotProjectFrame iotProductFrameDo = new  IotProjectFrame();
                        iotProductFrameDo.setProjectId(iotProductFrameDo.getId());
                        List<IotProjectFrame> iotProjectFrameDoList = iotProjectFrameDoService.selectIotProjectFrameList(iotProductFrameDo);
                        iotProjectFrameDoList.forEach(item -> {
                            Integer frameType = item.getFrameType().intValue();
                            EFrame eFrame = EFrame.getType(frameType.intValue());
                            tcpNetty.addHandler(TCPDispatchHandlerFactory.create(eFrame));
                        });
                        nettyTask.put(productId, tcpNetty);
                        executorService.execute(tcpNetty);
                        log.info(String.format("operation:{0} start product {1} ",operatorId,productId));
                    }
                      break;
                }
                iotProjectDo.setStartTime(new Date());
                iotProjectDo.setState(EProductState.run.getValue().longValue());

                iotProductDoService.updateIotProject(iotProjectDo);
                resultVO.setSuccess(true);
                resultVO.setCode(ECodeEnum.Success.getCode());
                resultVO.setMessage(ECodeEnum.Success.getMsg());
                resultVO.setData(iotProjectDo.getName());
            }
            break;
            case run: {
                resultVO.setSuccess(false);
                resultVO.setCode(ECodeEnum.ProductAlreadyRun.getCode());
                resultVO.setMessage(ECodeEnum.ProductAlreadyRun.getMsg());
                resultVO.setData(iotProjectDo.getName());
            }
            break;
            case noPay:{
                resultVO.setSuccess(false);
                resultVO.setCode(ECodeEnum.ProductNoPay.getCode());
                resultVO.setMessage(ECodeEnum.ProductNoPay.getMsg());
                resultVO.setData(iotProjectDo.getName());
            }
            break;
            case expire:{
                resultVO.setSuccess(false);
                resultVO.setCode(ECodeEnum.ProductExpire.getCode());
                resultVO.setMessage(ECodeEnum.ProductExpire.getMsg());
                resultVO.setData(iotProjectDo.getName());
            }
            break;
        }
        return resultVO;
    }





    @PostMapping("stop")
    public ResultVO<String> stopProductServer(PlatformProjectDTO platformProjectDTO) {
        Long projectId = platformProjectDTO.getProjectId();
        Task task = nettyTask.get(projectId);
        ResultVO<String> resultVO = new ResultVO<>();
        if(task == null) {
            resultVO.setSuccess(false);
            resultVO.setCode(ECodeEnum.ProductNoRunTask.getCode());
            resultVO.setMessage(ECodeEnum.ProductNoRunTask.getMsg());
            return resultVO;
        }
        IotProject iotProductDo = iotProductDoService.selectIotProjectById(projectId);
        Long operatorId  = platformProjectDTO.getOperatorId();
        if(iotProductDo.getCreator() != operatorId) {
            resultVO.setSuccess(false);
            resultVO.setCode(ECodeEnum.UserNoPermission.getCode());
            resultVO.setMessage(ECodeEnum.UserNoPermission.getMsg());
            resultVO.setData(iotProductDo.getName());
            return resultVO;
        }

        switch (EProductState.getType(iotProductDo.getState().intValue())) {
            case run:{
                task.cancel();
                resultVO.setSuccess(true);
                resultVO.setCode(ECodeEnum.ProductRunStop.getCode());
                resultVO.setMessage(ECodeEnum.ProductRunStop.getMsg());
                resultVO.setData(iotProductDo.getName());
                iotProductDo.setState(EProductState.stop.getValue().longValue());
                iotProductDoService.updateIotProject(iotProductDo);
                nettyTask.remove(projectId);
            }
            break;
            default:{
                resultVO.setSuccess(true);
                resultVO.setCode(ECodeEnum.ProductRunStop.getCode());
                resultVO.setMessage(ECodeEnum.ProductRunStop.getMsg());
                resultVO.setData(iotProductDo.getName());
            }
            break;
        }
        return resultVO;
    }
















}
